/*
*		
*		A compilacao e feita por: gcc -o montecarlo_gmp montecarlo_gmp.c -lgmp -lm 
*
*/

#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <math.h>
#include <gmp.h> 

#define KICKS  ULONG_MAX
#define BASE 10
#define MANTISSA 1024*1024*32  


//gera valores aleatorios
int get_random()
{
	int fd, nrandom;
	fd = open("/dev/random", O_RDONLY);
	read(fd, &nrandom, sizeof(nrandom));
	close(fd);
	return nrandom;
}


int main(int argc, char *argv[])
{
	unsigned long int i, hits = 0; // variaveis auxiliares
	time_t t_zero, t_final;
	double delta_t;
	double X, Y, R;
	int cmp;

	// Marca o tmepo 
	time(&t_zero);

	// Configura seed das funcoes Random
	srand(get_random());	

	// Float com precisao arbitratia
	mpf_set_default_prec(MANTISSA);
	mpf_t pi;

	for(i = 0; i < KICKS; i++)
	{
		// Distribuicao uniforme 0<x<1;
		X = (double) rand()/ (double) RAND_MAX;
		Y = (double) rand()/ (double) RAND_MAX;		    

		// Pitagoras
		// R = sqrt(X^2) + (Y^2)
		R = (X * X)+(Y * Y);
		// R = sqrt(R)
		R = sqrt(R); 
		
		//Avaliacao
		if(R <= 1) { hits++; }
	}
		
	
	mpf_init(pi);
	// pi = hits
	mpf_set_ui(pi, hits);
	// pi = pi / KICKS
	mpf_div_ui(pi, pi, KICKS);  
	// pi = pi * 4
	mpf_mul_ui(pi, pi, 4);  

	//mostra o valor de pi
	mpf_out_str(NULL, BASE, 0, pi);
	
	// Libera a memoria
	mpf_clear(pi);

	//mostra o tempo
	time(&t_final);	
	delta_t  = difftime(t_final, t_zero);
	printf("\nTempo = %.2lf segundos\n", delta_t);
		
	return 0;
}
